#include <glib.h>


static const int MaxThreadNum = 3;
static const int MaxJobNum = 6;
static const int JobTime1 = 500;
static const int JobTime2 = 500;
static GThreadPool *pool = NULL;
static int done = 0;

static void thread_pool_func(gpointer data, gpointer user_data)
{
    int job = GPOINTER_TO_INT(data);
    g_print("thread(0x%p) job(%d): start...\n", g_thread_self(), job);

    g_usleep(JobTime1*1000);
    g_print("thread(0x%p) job(%d): mid\n", g_thread_self(), job);
    g_usleep(JobTime2*1000);
    g_print("running %d, unprocessed %d, unused %d\n"
            , g_thread_pool_get_num_threads(pool)
            , g_thread_pool_unprocessed(pool)
            , g_thread_pool_get_num_unused_threads()
            );

    done++;
    g_print("thread(0x%p) job(%d): over\n", g_thread_self(), job);

}

static void show_exclusive_thread_pool(void)
{
    GError *err = NULL;
    gboolean ok;
    int max_num, max_unused;

    g_print("Show exclusive thread pool......\n");
    
    done = 0;
    pool = g_thread_pool_new(thread_pool_func       //GFunc
            , NULL                                  //user_data
            , MaxThreadNum                          //max_threads 
            , TRUE                                  //eclusive. exclusive thread pool始终运行max_threads数量的thread. idle time无意义.
            , &err
            );

    g_assert_no_error(err);
    g_assert_nonnull(pool);

    max_num = g_thread_pool_get_max_threads(pool);
    g_assert_cmpint(max_num, ==, MaxThreadNum);
    max_unused = g_thread_pool_get_max_unused_threads();
    g_print("max %d, max unused %d\n"
            , max_num
            , max_unused
            );
    g_print("running %d, unprocessed %d, unused %d\n"
            , g_thread_pool_get_num_threads(pool)
            , g_thread_pool_unprocessed(pool)
            , g_thread_pool_get_num_unused_threads()
            );

    //set_max_idle_time对于exclusive threadpool 无效，因max thread始终处于运行态
    g_print("idle %d, sleep %d\n", 100, 1000);
    g_thread_pool_set_max_idle_time(100);
    g_usleep(1000);
    g_print("running %d, unprocessed %d, unused %d\n"
            , g_thread_pool_get_num_threads(pool)
            , g_thread_pool_unprocessed(pool)
            , g_thread_pool_get_num_unused_threads()
            );


    for(int i = 1; i<= MaxJobNum; i++)
    {
        g_print("push job %d\n", i);
        ok = g_thread_pool_push(pool, GINT_TO_POINTER(i), &err);
        if(!ok)
        {
            g_print("fail to push new job\n");
            continue;
        }
        g_assert_true(ok);
        g_assert_no_error(err);

        g_usleep(10000);
        g_print("running %d, unprocessed %d, unused %d\n"
                , g_thread_pool_get_num_threads(pool)
                , g_thread_pool_unprocessed(pool)
                , g_thread_pool_get_num_unused_threads()
                );
    }

    while(done < MaxJobNum)
    {
        // g_print("%d\n", done);
        g_usleep(100);
    }

    g_print("waiting...\n");
    g_thread_pool_free(pool
            , FALSE                  //immediate.  FALSE, 处理完等待的job
            , TRUE);                //wait
}

static void show_nonexclusive_thread_pool(void)
{
    GError *err = NULL;
    gboolean ok;
    int max_num, max_unused;

    g_print("Show non exclusive thread pool......\n");

    done = 0;

    pool = g_thread_pool_new(thread_pool_func       //GFunc
            , NULL                                  //user_data
            , MaxThreadNum                          //max_threads 
            , FALSE                                  //eclusive. exclusive thread pool始终运行max_threads数量的thread. idle time无意义.
            , &err
            );

    g_assert_no_error(err);
    g_assert_nonnull(pool);

    max_num = g_thread_pool_get_max_threads(pool);
    g_assert_cmpint(max_num, ==, MaxThreadNum);
    max_unused = g_thread_pool_get_max_unused_threads();
    g_print("max %d, max unused %d\n"
            , max_num
            , max_unused
            );
    g_print("running %d, unprocessed %d, unused %d\n"
            , g_thread_pool_get_num_threads(pool)
            , g_thread_pool_unprocessed(pool)
            , g_thread_pool_get_num_unused_threads()
            );

    //set_max_idle_time对于exclusive threadpool 无效，因max thread始终处于运行态
    g_print("idle %d, sleep %d\n", 100, 1000);
    g_thread_pool_set_max_idle_time(100);
    g_usleep(1000);
    g_print("running %d, unprocessed %d, unused %d\n"
            , g_thread_pool_get_num_threads(pool)
            , g_thread_pool_unprocessed(pool)
            , g_thread_pool_get_num_unused_threads()
            );


    for(int i = 1; i<= MaxJobNum; i++)
    {
        g_print("push job %d\n", i);
        ok = g_thread_pool_push(pool, GINT_TO_POINTER(i), &err);
        if(!ok)
        {
            g_print("fail to push new job\n");
            continue;
        }
        g_assert_true(ok);
        g_assert_no_error(err);

        g_usleep(10000);
        g_print("running %d, unprocessed %d, unused %d\n"
                , g_thread_pool_get_num_threads(pool)
                , g_thread_pool_unprocessed(pool)
                , g_thread_pool_get_num_unused_threads()
                );
    }

    while(done < MaxJobNum)
    {
        g_usleep(100);
    }

    g_thread_pool_free(pool
            , FALSE                  //immediate.  FALSE, 处理完等待的job
            , TRUE);                //wait
}

int main(int argc, char* argv[])
{
    show_exclusive_thread_pool();
    show_nonexclusive_thread_pool();
    return 0;
}